package com.ms3ds.deviceData.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ms3ds.common.core.domain.R;
import com.ms3ds.common.core.utils.DateUtils;
import com.ms3ds.mineInfo.api.RemoteAreaService;
import com.ms3ds.mineInfo.api.RemoteMineService;
import com.ms3ds.mineInfo.api.domain.Area;
import com.ms3ds.mineInfo.api.domain.Mine;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ms3ds.deviceData.mapper.FootageMapper;
import com.ms3ds.deviceData.domain.Footage;
import com.ms3ds.deviceData.service.IFootageService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 进尺数据Service业务层处理
 * 
 * @author zlw
 * @date 2025-09-21
 */
@Service
public class FootageServiceImpl implements IFootageService 
{
    @Autowired
    private FootageMapper footageMapper;
    @Autowired
    private RemoteMineService remoteMineService; // 注入远程服务

    @Autowired
    private RemoteAreaService remoteAreaService; // 注入区域远程服务

    private final Random random = new Random();


    /**
     * 查询进尺数据
     * 
     * @param id 进尺数据主键
     * @return 进尺数据
     */
    @Override
    public Footage selectFootageById(Long id)
    {
        return footageMapper.selectFootageById(id);
    }

    /**
     * 查询进尺数据列表
     * 
     * @param footage 进尺数据
     * @return 进尺数据
     */
    @Override
    public List<Footage> selectFootageList(Footage footage)
    {
        return footageMapper.selectFootageList(footage);
    }

    /**
     * 新增进尺数据
     * 
     * @param footage 进尺数据
     * @return 结果
     */
    @Override
    public int insertFootage(Footage footage)
    {
        return footageMapper.insertFootage(footage);
    }

    /**
     * 修改进尺数据
     * 
     * @param footage 进尺数据
     * @return 结果
     */
    @Override
    public int updateFootage(Footage footage)
    {
        return footageMapper.updateFootage(footage);
    }

    /**
     * 批量删除进尺数据
     * 
     * @param ids 需要删除的进尺数据主键
     * @return 结果
     */
    @Override
    public int deleteFootageByIds(Long[] ids)
    {
        return footageMapper.deleteFootageByIds(ids);
    }

    /**
     * 删除进尺数据信息
     * 
     * @param id 进尺数据主键
     * @return 结果
     */
    @Override
    public int deleteFootageById(Long id)
    {
        return footageMapper.deleteFootageById(id);
    }



    /**
     * 生成符合三条业务规则的测试数据 - 为所有区域添加数据
     */


    @Override
    @Transactional
    public int addTestFootageDataWithRule() {
        int totalCount = 0;

        // 获取所有矿山信息
        R<List<Mine>> mineResult = remoteMineService.getAllForRemote();
        if (mineResult == null || mineResult.getData() == null || mineResult.getData().isEmpty()) {
            return 0;
        }

        List<Mine> mines = mineResult.getData();

        // 遍历所有矿山
        for (Mine mine : mines) {
            // 获取该矿山的所有区域
            R<List<Area>> areaResult = remoteAreaService.getAreaListByMineIdForRemote(mine.getId());
            if (areaResult != null && areaResult.getData() != null && !areaResult.getData().isEmpty()) {
                List<Area> areas = areaResult.getData();

                // 遍历该矿山的所有区域
                for (Area area : areas) {
                    // 为同一个区域模拟两种类型的进尺数据（类型1和类型2）
                    for (int footageType = 1; footageType <= 2; footageType++) {
                        Long areaId = area.getId();
                        Float lastStop = footageMapper.getLastStopDataByType(footageType, areaId);

                        /* ---------- 规则落地 ---------- */
                        float beginData = (lastStop == null) ? 0F : lastStop;        // 规则1+2
                        float stopData  = beginData + random.nextFloat() * 2;      // 规则3：差值 0~2

                        Footage footage = new Footage();
                        footage.setAreaId(areaId);
                        footage.setFootageType((long) footageType);
                        footage.setBeginData(beginData);
                        footage.setStopData(stopData);
                        footage.setTime(DateUtils.getNowDate());

                        int result = footageMapper.insertFootage(footage);
                        totalCount += result;
                    }
                }
            }
        }

        return totalCount;
    }

    /**
     * 根据矿山ID获取图表数据
     * @param mineId 矿山ID
     * @return 图表数据
     */
    @Override
    public R<Map<String, Object>> getFootageChartDataByMineId(Long mineId) {
        // 验证矿山是否存在
        R<List<Mine>> mineResult = remoteMineService.getAllForRemote();
        if (mineResult == null || mineResult.getData() == null || mineResult.getData().isEmpty()) {
            return R.fail("未找到矿山信息");
        }

        boolean mineExists = mineResult.getData().stream()
                .anyMatch(mine -> mine.getId().equals(mineId));

        if (!mineExists) {
            return R.fail("指定的矿山不存在");
        }

        // 获取该矿山的所有区域
        R<List<Area>> areaResult = remoteAreaService.getAreaListByMineIdForRemote(mineId);
        if (areaResult == null || areaResult.getData() == null || areaResult.getData().isEmpty()) {
            return R.fail("该矿山下未找到区域信息");
        }

        List<Area> areas = areaResult.getData();
        List<Long> areaIds = areas.stream().map(Area::getId).collect(Collectors.toList());

        // 创建areaId到areaName的映射
        Map<Long, String> areaIdToNameMap = areas.stream()
                .collect(Collectors.toMap(Area::getId, Area::getAreaName));

        // 创建areaId到areaLength的映射
        Map<Long, Long> areaIdToLengthMap = areas.stream()
                .collect(Collectors.toMap(Area::getId, Area::getAreaLength));

        // 构建返回数据结构
        Map<String, Object> chartData = new HashMap<>();

        // 初始化年、月、日的数据列表
        List<Map<String, Object>> yearExploitList = new ArrayList<>();
        List<Map<String, Object>> monthExploitList = new ArrayList<>();
        List<Map<String, Object>> dayExploitList = new ArrayList<>();

        List<Map<String, Object>> yearDrivageList = new ArrayList<>();
        List<Map<String, Object>> monthDrivageList = new ArrayList<>();
        List<Map<String, Object>> dayDrivageList = new ArrayList<>();

        // 遍历所有区域
        for (Long areaId : areaIds) {
            String areaName = areaIdToNameMap.get(areaId);
            Long areaLength = areaIdToLengthMap.get(areaId);

            // 查询开采类型(footage_type=1)的数据
            Footage queryExploit = new Footage();
            queryExploit.setAreaId(areaId);
            queryExploit.setFootageType(1L);
            List<Footage> exploitList = footageMapper.selectFootageList(queryExploit);

            // 处理开采数据
            if (!exploitList.isEmpty()) {
                // 按时间排序
                List<Footage> sortedExploit = exploitList.stream()
                        .sorted(Comparator.comparing(Footage::getTime))
                        .collect(Collectors.toList());

                // 计算年进尺：过去一年范围内最新数据的stop_data - 最老数据的begin_data
                Date oneYearAgo = DateUtils.addYears(new Date(), -1);
                List<Footage> yearRangeData = sortedExploit.stream()
                        .filter(f -> f.getTime().after(oneYearAgo))
                        .collect(Collectors.toList());

                Double yearFootage = null;
                if (!yearRangeData.isEmpty()) {
                    Footage yearOldest = yearRangeData.get(0);
                    Footage yearLatest = yearRangeData.get(yearRangeData.size() - 1);
                    yearFootage = (double) (yearLatest.getStopData() - yearOldest.getBeginData());
                }

                // 计算月进尺：过去一个月范围内最新数据的stop_data - 最老数据的begin_data
                Date oneMonthAgo = DateUtils.addMonths(new Date(), -1);
                List<Footage> monthRangeData = sortedExploit.stream()
                        .filter(f -> f.getTime().after(oneMonthAgo))
                        .collect(Collectors.toList());

                Double monthFootage = null;
                if (!monthRangeData.isEmpty()) {
                    Footage monthOldest = monthRangeData.get(0);
                    Footage monthLatest = monthRangeData.get(monthRangeData.size() - 1);
                    monthFootage = (double) (monthLatest.getStopData() - monthOldest.getBeginData());
                }

                // 计算日进尺：过去一天范围内最新数据的stop_data - 最老数据的begin_data
                Date oneDayAgo = DateUtils.addDays(new Date(), -1);
                List<Footage> dayRangeData = sortedExploit.stream()
                        .filter(f -> f.getTime().after(oneDayAgo))
                        .collect(Collectors.toList());

                Double dayFootage = null;
                if (!dayRangeData.isEmpty()) {
                    Footage dayOldest = dayRangeData.get(0);
                    Footage dayLatest = dayRangeData.get(dayRangeData.size() - 1);
                    dayFootage = (double) (dayLatest.getStopData() - dayOldest.getBeginData());
                }

                // 构建年数据项
                Map<String, Object> yearExploitItem = new HashMap<>();
                yearExploitItem.put("area_id", areaId);
                yearExploitItem.put("area_name", areaName);
                yearExploitItem.put("total", areaLength);
                yearExploitItem.put("real", yearFootage != null ? yearFootage : 0);

                String yearFootagePercentage = "0%";
                if (areaLength != null && areaLength != 0 && yearFootage != null) {
                    double yearPercentage = (yearFootage * 100.0) / areaLength;
                    yearFootagePercentage = String.format("%.2f", yearPercentage) + "%";
                }
                yearExploitItem.put("percentage", yearFootagePercentage);
                yearExploitList.add(yearExploitItem);

                // 构建月数据项
                Map<String, Object> monthExploitItem = new HashMap<>();
                monthExploitItem.put("area_id", areaId);
                monthExploitItem.put("area_name", areaName);
                monthExploitItem.put("total", areaLength);
                monthExploitItem.put("real", monthFootage != null ? monthFootage : 0);

                String monthFootagePercentage = "0%";
                if (areaLength != null && areaLength != 0 && monthFootage != null) {
                    double monthPercentage = (monthFootage * 100.0) / areaLength;
                    monthFootagePercentage = String.format("%.2f", monthPercentage) + "%";
                }
                monthExploitItem.put("percentage", monthFootagePercentage);
                monthExploitList.add(monthExploitItem);

                // 构建日数据项
                Map<String, Object> dayExploitItem = new HashMap<>();
                dayExploitItem.put("area_id", areaId);
                dayExploitItem.put("area_name", areaName);
                dayExploitItem.put("total", areaLength);
                dayExploitItem.put("real", dayFootage != null ? dayFootage : 0);

                String dayFootagePercentage = "0%";
                if (areaLength != null && areaLength != 0 && dayFootage != null) {
                    double dayPercentage = (dayFootage * 100.0) / areaLength;
                    dayFootagePercentage = String.format("%.2f", dayPercentage) + "%";
                }
                dayExploitItem.put("percentage", dayFootagePercentage);
                dayExploitList.add(dayExploitItem);
            }

            // 查询掘进类型(footage_type=2)的数据
            Footage queryDrivage = new Footage();
            queryDrivage.setAreaId(areaId);
            queryDrivage.setFootageType(2L);
            List<Footage> drivageList = footageMapper.selectFootageList(queryDrivage);

            // 处理掘进数据
            if (!drivageList.isEmpty()) {
                // 按时间排序
                List<Footage> sortedDrivage = drivageList.stream()
                        .sorted(Comparator.comparing(Footage::getTime))
                        .collect(Collectors.toList());

                // 计算年进尺：过去一年范围内最新数据的stop_data - 最老数据的begin_data
                Date oneYearAgo = DateUtils.addYears(new Date(), -1);
                List<Footage> drivageYearRangeData = sortedDrivage.stream()
                        .filter(f -> f.getTime().after(oneYearAgo))
                        .collect(Collectors.toList());

                Double drivageYearFootage = null;
                if (!drivageYearRangeData.isEmpty()) {
                    Footage yearOldest = drivageYearRangeData.get(0);
                    Footage yearLatest = drivageYearRangeData.get(drivageYearRangeData.size() - 1);
                    drivageYearFootage = (double) (yearLatest.getStopData() - yearOldest.getBeginData());
                }

                // 计算月进尺：过去一个月范围内最新数据的stop_data - 最老数据的begin_data
                Date oneMonthAgo = DateUtils.addMonths(new Date(), -1);
                List<Footage> drivageMonthRangeData = sortedDrivage.stream()
                        .filter(f -> f.getTime().after(oneMonthAgo))
                        .collect(Collectors.toList());

                Double drivageMonthFootage = null;
                if (!drivageMonthRangeData.isEmpty()) {
                    Footage monthOldest = drivageMonthRangeData.get(0);
                    Footage monthLatest = drivageMonthRangeData.get(drivageMonthRangeData.size() - 1);
                    drivageMonthFootage = (double) (monthLatest.getStopData() - monthOldest.getBeginData());
                }

                // 计算日进尺：过去一天范围内最新数据的stop_data - 最老数据的begin_data
                Date oneDayAgo = DateUtils.addDays(new Date(), -1);
                List<Footage> drivageDayRangeData = sortedDrivage.stream()
                        .filter(f -> f.getTime().after(oneDayAgo))
                        .collect(Collectors.toList());

                Double drivageDayFootage = null;
                if (!drivageDayRangeData.isEmpty()) {
                    Footage dayOldest = drivageDayRangeData.get(0);
                    Footage dayLatest = drivageDayRangeData.get(drivageDayRangeData.size() - 1);
                    drivageDayFootage = (double) (dayLatest.getStopData() - dayOldest.getBeginData());
                }

                // 构建年数据项
                Map<String, Object> yearDrivageItem = new HashMap<>();
                yearDrivageItem.put("area_id", areaId);
                yearDrivageItem.put("area_name", areaName);
                yearDrivageItem.put("total", areaLength);
                yearDrivageItem.put("real", drivageYearFootage != null ? drivageYearFootage : 0);

                String yearFootagePercentage = "0%";
                if (areaLength != null && areaLength != 0 && drivageYearFootage != null) {
                    double yearPercentage = (drivageYearFootage * 100.0) / areaLength;
                    yearFootagePercentage = String.format("%.2f", yearPercentage) + "%";
                }
                yearDrivageItem.put("percentage", yearFootagePercentage);
                yearDrivageList.add(yearDrivageItem);

                // 构建月数据项
                Map<String, Object> monthDrivageItem = new HashMap<>();
                monthDrivageItem.put("area_id", areaId);
                monthDrivageItem.put("area_name", areaName);
                monthDrivageItem.put("total", areaLength);
                monthDrivageItem.put("real", drivageMonthFootage != null ? drivageMonthFootage : 0);

                String monthFootagePercentage = "0%";
                if (areaLength != null && areaLength != 0 && drivageMonthFootage != null) {
                    double monthPercentage = (drivageMonthFootage * 100.0) / areaLength;
                    monthFootagePercentage = String.format("%.2f", monthPercentage) + "%";
                }
                monthDrivageItem.put("percentage", monthFootagePercentage);
                monthDrivageList.add(monthDrivageItem);

                // 构建日数据项
                Map<String, Object> dayDrivageItem = new HashMap<>();
                dayDrivageItem.put("area_id", areaId);
                dayDrivageItem.put("area_name", areaName);
                dayDrivageItem.put("total", areaLength);
                dayDrivageItem.put("real", drivageDayFootage != null ? drivageDayFootage : 0);

                String dayFootagePercentage = "0%";
                if (areaLength != null && areaLength != 0 && drivageDayFootage != null) {
                    double dayPercentage = (drivageDayFootage * 100.0) / areaLength;
                    dayFootagePercentage = String.format("%.2f", dayPercentage) + "%";
                }
                dayDrivageItem.put("percentage", dayFootagePercentage);
                dayDrivageList.add(dayDrivageItem);
            }
        }

        // 构建最终返回结构
        Map<String, Object> exploitData = new HashMap<>();
        exploitData.put("year", yearExploitList);
        exploitData.put("month", monthExploitList);
        exploitData.put("day", dayExploitList);

        Map<String, Object> drivageData = new HashMap<>();
        drivageData.put("year", yearDrivageList);
        drivageData.put("month", monthDrivageList);
        drivageData.put("day", dayDrivageList);

        Map<String, Object> result = new HashMap<>();
        result.put("exploit", exploitData);
        result.put("drivage", drivageData);
        chartData.put("chartData", result);

        return R.ok(chartData);
    }


}